package com.vken.blog.dao.hibernate;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.List;
import org.hibernate.*;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.vken.blog.dao.GenericDao;
import com.vken.blog.util.Pagination;

public abstract class GenericDaoHibernate<T, PK extends Serializable> extends HibernateDaoSupport
		implements GenericDao<T, PK> {
	private Class<T> clazz;

	public GenericDaoHibernate() {
		clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
				.getActualTypeArguments()[0];
	}

	public T findById(PK id) {
		return (T) getHibernateTemplate().get(clazz, id);
	}

	public List<T> findAll() {
		return getHibernateTemplate().find("from " + clazz.getName());
	}

	public T save(T entity) {
		getHibernateTemplate().save(entity);
		return entity;
	}

	public void update(T entity) {
		getHibernateTemplate().update(entity);
	}

	public void delete(T entity) {
		getHibernateTemplate().delete(entity);
	}

	public Object queryObject(final String hql, final Object[] params) {
		return getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.createQuery(hql);
				if (params != null) {
					for (int i = 0; i < params.length; i++) {
						query.setParameter(i, params);
					}
				}
				return query.uniqueResult();
			}
		});
	}

	public Pagination getPagination(final String hql, final Object params[], final int pageSize,
			final int pageNumber, final int totalCount) {
		return ((Pagination) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				Pagination pagination = new Pagination(pageSize, pageNumber, totalCount);
				Query query = session.createQuery(hql);
				if (params != null) {
					for (int i = 0; i < params.length; i++) {
						query.setParameter(i, params);
					}
				}
				query.setMaxResults(pageSize);
				query.setFirstResult((pageNumber - 1) * pageSize);
				pagination.setList(query.list());
				return pagination;
			}
		}));
	}
}
